#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <ctype.h>
#include <locale.h>
#include <stdlib.h>
#include <wchar.h>

struct arg_set         /* tow values in one arg */
{
  char *fname;         /* file to examine */
  int count;           /* number of words */
};

struct arg_set *mailbox;

pthread_mutex_t lock;
pthread_cond_t flag;

int main(int argc, char *argv[], char *env[])
{
  setlocale(LC_ALL, "");

  if(argc != 3) {
    fwprintf(stderr, L"usage: %s file1 file2\n", argv[0]);
    exit(1);
  }

  struct arg_set args1, args2;

  pthread_mutex_init(&lock, NULL);
  pthread_cond_init(&flag, NULL);

  pthread_t t1, t2;
  void *count_words(void *);
  int reports_in = 0, total_words = 0;

  pthread_mutex_lock(&lock);

  args1.fname = argv[1];
  args1.count = 0;
  pthread_create(&t1, NULL, count_words, (void *)&args1);

  args2.fname = argv[2];
  args2.count = 0;
  pthread_create(&t2, NULL, count_words, (void *)&args2);

  fputws(L"注意这里的循环里没有 pthread_mutex_lock 和 pthread_mutex_unlock\n", stdout);
  while(reports_in < 2) {
    fputws(L"MAIN: waiting for flag to go up\n", stdout);
    while(mailbox == NULL) /* 虽然书上没写这一个判断，但是这个判断是必须有的 */
      pthread_cond_wait(&flag, &lock);
    fputws(L"MAIN: Wow! flag was raised, I have the lock!\n", stdout);
    wprintf(L"%7d: %s\n", mailbox->count, mailbox->fname);
    total_words += mailbox->count;
    if(mailbox == &args1)
      pthread_join(t1, NULL);
    if(mailbox == &args2)
      pthread_join(t2, NULL);
    mailbox = NULL;
    pthread_cond_signal(&flag);
    ++reports_in;
  }

  pthread_mutex_unlock(&lock);

  wprintf(L"%7d: total words\n", total_words);
  return EXIT_SUCCESS;
}


void *count_words(void *a)
{
  struct arg_set *args = a;
 
  FILE *fp = NULL;
  int c, prevc = '\0';

  if((fp = fopen(args->fname, "r")) == NULL) {
    perror(args->fname);
    return NULL;
  }

  while((c = fgetc(fp)) != EOF) {
    if(!isalnum(c) && isalnum(prevc))
      ++args->count;
    prevc = c;
  }
  fclose(fp);
  fputws(L"COUNT: waiting to get lock\n", stdout);   /* get the mailbox */
  pthread_mutex_lock(&lock);
  fputws(L"COUNT: have lock, storing data\n", stdout);
  while(mailbox != NULL) {
    fputws(L"COUNT: mailbox is not empty, waiting to free\n", stdout);
    pthread_cond_wait(&flag, &lock);
  }
  mailbox = args;  /* put ptr to our args there */
  fputws(L"COUNT: mailfox is free, storing the mail and raising flag\n", stdout);
  pthread_cond_signal(&flag);  /* raise the flag */
  fputws(L"COUNT: unlocking box\n", stdout);
  pthread_mutex_unlock(&lock); /* release the mailbox */
  return NULL;
}
